;(() => {
  // class Counter {
  //   constructor(public count: number = 0) {}
  //   add(value: number) {
  //     this.count += value
  //     return this
  //   }
  //   substract(value: number) {
  //     this.count -= value
  //     return this
  //   }
  // }
  // let counter1 = new Counter(10)
  // // console.log(counter1)
  // // console.log(counter1.add(55).substract(15))
  // class PowCounter extends Counter {
  //   constructor(public count: number = 10) {
  //     super(count)
  //   }
  //   pow(value: number) {
  //     this.count = this.count ** value
  //     return this
  //   }
  // }
  // let powCounter = new PowCounter()
  // console.log(powCounter)
  // console.log(powCounter.pow(2).add(4).substract(20))
  // 索引类型查询操作符 keyof
  // interface Infos {
  //   name: string
  //   age: number
  // }
  // let info: keyof Infos
  // info = 'age'
  // info = 'name'
  // // info = 'sex' // 报错 没有这个属性名
  // function getValue<T, K extends keyof T>(obj: T, names: K[]): Array<T[K]> {
  //   return names.map(n => obj[n])
  // }
  // const infoObj = {
  //   name: '刘柏麟',
  //   age: 24,
  //   sex: '男',
  // }
  // const arr: Array<string | number> = getValue(infoObj, ['name', 'age', 'sex'])
  // console.log(arr)
  // // [] 索引访问操作符
  // type NameTypes = Infos['name']
  // function getProperty<T, K extends keyof T>(obj: T, name: K): T[K] {
  //   return obj[name]
  // }
  // interface Objs<T> {
  //   [key: string]: T
  // }
  // const obj1: Objs<number> = {
  //   age: 18,
  // }
  // let keys: Objs<number>['name'] = 123123
  // interface Type {
  //   a: never
  //   b: never
  //   c: string
  //   d: number
  //   e: undefined
  //   f: null
  //   g: object
  // }
  // // 非never得类型
  // type Test = Type[keyof Type]
  // interface Info1 {
  //   age: number
  //   name: string
  //   sex?: string
  // }
  // type ReadonlyType<T> = {
  //   readonly [P in keyof T]: T[P]
  // }
  // type Readonly1 = ReadonlyType<Info1>
  // const obj: Readonly1 = {
  //   age: 18,
  //   name: '胭脂',
  // }
  // console.log(obj)
  // obj.name = 111 报错 因为是只读属性
  // interface UserInfo {
  //   name: string
  //   age: number
  //   sex: string
  // }
  // const name: UserInfo['name'] = '123'
  // type Readonly<T> = {
  //   readonly [P in keyof T]: T[P]
  // }
  // function getObj<T, K extends keyof T>(obj: T, name: K): T[K] {
  //   return obj[name]
  // }
  // type UserInfo2<T> = {
  //   readonly [P in keyof T]: T[P]
  // }
  // Ts内置映射类型  只读Readonly  可选Partial
  // interface UserInfo {
  //   name: string
  //   age: number
  //   sex: string
  // }
  // const user: Readonly<UserInfo> = {
  //   name: '1',
  //   age: 222,
  //   sex: '11',
  // }
  // const user1: Partial<UserInfo> = {
  //   name: '1',
  //   age: 222,
  //   sex: '11',
  // }
  // type Pick<T, K extends keyof T> = {
  //   [P in K]: T[P]
  // }
  // type Record<K extends keyof any, T> = {
  //   [P in K]: T
  // }
  // interface Info2 {
  //   name: string
  //   age: number
  //   address: string
  // }
  // const info: Info2 = {
  //   name: '1111',
  //   age: 1111,
  //   address: '1111',
  // }
  // function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
  //   let res: any = {}
  //   keys.map(key => {
  //     res[key] = obj[key]
  //   })
  //   return res
  // }
  // console.log(pick(info, ['name', 'age']))
  // const info222: Pick<Info2, keyof Info2> = {
  //   name: '222',
  //   age: 1111,
  //   address: '222',
  // }
  // const info333: Pick<Info2, 'name' | 'address'> = {
  //   name: '12312',
  //   address: '123',
  // }
  // function aaa<T, K extends keyof T>(obj: T, keys: K) {
  //   return obj[keys]
  // }
  // aaa(info222, 'name')
  // let userInfo: Pick<Info2, > = {
  // }
  // interface Info1111 extends Info2 {}
  // const user11: Info1111 = {
  //   name: 's',
  //   address: '11',
  //   age: 11,
  // }、
  // interface IUserInfo {
  //   name: string
  //   age: number
  //   sex: string
  // }
  // const userInfo: Pick<IUserInfo, 'name' | 'age'> = {
  //   name: '胭脂',
  //   age: 18,
  // }
  // console.log(userInfo)
  // function mapObject<K extends keyof any, T, U>(
  //   obj: Record<K, T>,
  //   f: (x: T) => U
  // ): Record<K, U> {
  //   let res: any = {}
  //   for (const key in obj) {
  //     res[key] = f(obj[key])
  //   }
  //   return res
  // }
  // const names = { 0: 'hello', 1: 'world', 2: 'bye' }
  // const lengths = mapObject(names, s => s.length)
  // console.log(lengths)
  // interface TArr {
  //   0: string
  //   1: number
  //   2: string
  // }
  // const arr: TArr = ['123', 111, '1231']
  // type IArr = {
  //   [key: string]: number
  // }
  // let arr: IArr = {
  //   0: 1,
  //   1: 2,
  //   33: 22,
  // }
  // console.log(arr)
  // 同态   Readonly ,Partail ,Pick
  // type Proxy<T> = {
  //   get(): T
  //   set(value: T): void
  // }
  // type Proxify<T> = {
  //   [P in keyof T]: Proxy<T[P]>
  // }
  // function proxify<T>(obj: T): Proxify<T> {
  //   const result = {} as Proxify<T>
  //   for (const key in obj) {
  //     result[key] = {
  //       get: () => obj[key],
  //       set: value => (obj[key] = value),
  //     }
  //   }
  //   return result
  // }
  // let props = {
  //   name: 'lison',
  //   age: 18,
  // }
  // let proxyProps = proxify(props)
  // proxyProps.name.set('li')
  // console.log(proxyProps.name.get())
  // function unproxify<T>(t: Proxify<T>): T {
  //   let result = {} as T
  //   for (const k in t) {
  //     result[k] = t[k].get()
  //   }
  //   return result
  // }
  // let originalProps = unproxify(proxyProps)
  // console.log(originalProps)
  // 增加或移除特定修饰符
  // interface User {
  //   name: string
  //   age: number
  //   sex: string
  // }
  // type Readonly<T> = {
  //   +readonly [P in keyof T]+?: T[P]
  // }
  // type RemoveReadonly<T> = {
  //   -readonly [P in keyof T]-?: T[P]
  // }
  // // const userInfo: Readonly<User> = {
  // //   name: '刘柏麟',
  // //   age: 19,
  // //   sex: '女',
  // // }
  // type ReadonlyInfo = Readonly<User>
  // type RemoveReadonlyInfo = RemoveReadonly<User>
  // const stringIndex = 'a'
  // const numberIndex = 1
  // const symbolIndex = Symbol()
  // type Objs2 = {
  //   [stringIndex]: string
  //   [numberIndex]: number
  //   [symbolIndex]: symbol
  // }
  // type keysType = keyof Objs2
  // // function add(value: keysType) {
  // //   console.log(value)
  // // }
  // // add(1)
  // type ReadonlyTypes<T> = {
  //   readonly [P in keyof T]: T[P]
  // }
  // const obj3: ReadonlyTypes<Objs2> = {
  //   a: '嘿嘿嘿',
  //   1: 123123,
  //   [symbolIndex]: Symbol(),
  // }
  // obj3.a = '' // 报错因为只是只读属性
  // 元祖和数组上的映射类型(生成新的元祖和数组,具有数组方法)
  // type MapToPromise<T> = {
  //   [K in keyof T]: Promise<T[K]>
  // }
  // type Tuple = [number, string, boolean]
  // type promiseTuple = MapToPromise<Tuple>
  // const tuple1: promiseTuple = [
  //   new Promise((resolve, reject) => resolve(1)),
  //   new Promise((resolve, reject) => resolve('2')),
  //   new Promise((resolve, reject) => resolve(true)),
  // ]
  // type Arr = [number, string, number]
  // function getadd<T, K extends keyof T>(x:T,y:K) {
  //   console.log(x,y);
  // }
  // const arr:Arr = [1,'2',1]
  // getadd(arr,0)
  // unknown
  //1. 任何类型都可以赋值给unknown类型
  // let value1: unknown
  // value1 = '1'
  // value1 = 123
  // //2. 如果没有类型断言或基于控制流的类型细化时,unknown不可以赋值给其他类型,此时他只能赋值给unknown和any类型
  // let value2: unknown
  // // let value3: string  =value2 //报错
  // value1 = value2
  // let Val: string = value2 as string
  // //3.如果没有类型断言或基于控制流的类型细化时，不能在上面进行任何操作
  // let value4: unknown
  // // value4 ++
  // //4. unknown与其他类型组成的交叉类型，最后都等于其他类型
  // type type1 = string & unknown
  // type type2 = number & unknown
  // type type3 = number[] & unknown
  // type type4 = unknown & unknown
  // // 5.unknown与其他任何类型(除了any)组成的联合类型,都等于unknown类型
  // type type5 = unknown | string
  // type type6 = unknown | number[]
  // type type7 = any | unknown
  // // 6.never类型是unknown的子类型
  // type type8 = never extends unknown ? true : false
  // // 7. keyof unknown 等于类型never
  // type type9 = keyof unknown
  // // 8. 只能对unknown进行等或不等操作，不能进行其他操作
  // value1 === value2
  // value1 !== value2
  // // value1 += value2 // 报错
  // // 9.unknown类型的值不能访问他的属性、作为函数调用和作为类创建实例
  // let value10: unknown
  // // value10.age // 报错
  // // value10() // 报错
  // // new value10() //报错
  // //10 使用映射类型时如果遍历的是unknown类型,则不会映射任何属性
  // type Type<T> = {
  //   [P in keyof T]: number
  // }
  // type type11 = Type<any>
  // type type22 = Type<unknown>
  // // 条件类型
  // // T extends U ? X : Y
  // type Types2<T> = T extends string ? string : number
  // // const index: Types2<'a'> = '11'
  // let myTypes: Types2<false> = 1111
  // // 分布式条件类型
  // // type TypeName<T> = T extends any ? T : never
  // // type type31 = TypeName<string | number>
  // type TypeName<T> = T extends string
  //   ? string
  //   : T extends number
  //   ? number
  //   : T extends boolean
  //   ? boolean
  //   : T extends undefined
  //   ? undefined
  //   : T extends () => void
  //   ? () => void
  //   : object
  // type type41 = TypeName<() => void>
  // type type51 = TypeName<number[]>
  // type type61 = TypeName<(() => void) | number[]>
  // type Diff<T, U> = T extends U ? never : T
  // type Test = Diff<string | number | boolean, undefined | number>
  // type Type7<T> = {
  //   [K in keyof T]: T[K] extends Function ? K : never
  // }[keyof T]
  // interface Part {
  //   id: number
  //   name: string
  //   subparts: Part[]
  //   updatePart(newValue: string): void
  //   updatePart1(newValue: string): void
  // }
  // type Test1 = Type7<Part>
  // 条件类型推断 infer关键字
  // type Type<T> = T extends any[] ? T[number] : T
  // type Test3 = Type<string[]>
  // type Test4 = Type<string>
  // infer 实现
  // type Type9<T> = T extends Array<infer U> ? U : T
  // type Test5 = Type9<string[]>
  // type Test6 = Type9<string>
  // 内置条件类型 Exclude<T,U> 选没有的
  // type Type10 = Exclude<'a' | 'b' | 'c', 'a' | 'b'>
  // // Extract<T,U> // 选取T中可以赋值给U的类型
  // type Type11 = Extract<'a' | 'b' | 'c', 'c'>
  // // NonNullable<T> 去掉null 和 undefined
  // type Type12 = NonNullable<string | number | null | undefined>
  // // returnType<T> 获取函数返回值类型
  // type Type13 = ReturnType<() => string>
  // // InstanceType<T> 获取构造函数的实例类型
  // class AClass {
  //   constructor() {}
  // }
  // type T1 = InstanceType<typeof AClass>
  // type T2 = InstanceType<any>
  // type T3 = InstanceType<never>
  // type T4 = InstanceType<string> // 报错
})()
